package org.dromara.vehicle.modules.carApply.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.service.WorkflowService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.vehicle.modules.carApply.domain.CarApply;
import org.dromara.vehicle.modules.carApply.domain.bo.ApplyBo;
import org.dromara.vehicle.modules.carApply.domain.bo.CarApplyBo;
import org.dromara.vehicle.modules.carApply.domain.vo.ApplyVo;
import org.dromara.vehicle.modules.carApply.domain.vo.CarApplyVo;
import org.dromara.vehicle.modules.carApply.mapper.CarApplyMapper;
import org.dromara.vehicle.modules.carApply.service.ICarApplyService;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 用车申请Service业务层处理
 *
 * @author ckk
 * @date 2025-06-27
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class CarApplyServiceImpl extends ServiceImpl<CarApplyMapper, CarApply> implements ICarApplyService {

    private final CarApplyMapper baseMapper;
    private final WorkflowService workflowService;

    /**
     * 查询用车申请
     *
     * @param id 主键
     * @return 用车申请
     */
    @Override
    public CarApplyVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询用车申请列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 用车申请分页列表
     */
    @Override
    public TableDataInfo<CarApplyVo> queryPageList(CarApplyBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CarApply> lqw = buildQueryWrapper(bo);
        Page<CarApplyVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的用车申请列表
     *
     * @param bo 查询条件
     * @return 用车申请列表
     */
    @Override
    public List<CarApplyVo> queryList(CarApplyBo bo) {
        LambdaQueryWrapper<CarApply> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CarApply> buildQueryWrapper(CarApplyBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CarApply> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(CarApply::getId);
        lqw.eq(bo.getUseReason() != null, CarApply::getUseReason, bo.getUseReason());
        lqw.eq(bo.getCarType() != null, CarApply::getCarType, bo.getCarType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CarApply::getStatus, bo.getStatus());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            CarApply::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        return lqw;
    }

    /**
     * 新增用车申请
     *
     * @param bo 用车申请
     * @return 是否新增成功
     */
    @Override
    public Long insertByBo(CarApplyBo bo) {
        CarApply add = MapstructUtils.convert(bo, CarApply.class);
        validEntityBeforeSave(add);
        add.setStatus(BusinessStatusEnum.DRAFT.getStatus());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return add.getId();
    }

    /**
     * 修改用车申请
     *
     * @param bo 用车申请
     * @return 是否修改成功
     */
    @Override
    public Long updateByBo(CarApplyBo bo) {
        CarApply update = MapstructUtils.convert(bo, CarApply.class);
        validEntityBeforeSave(update);
        baseMapper.updateById(update);
        return  bo.getId();
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CarApply entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除用车申请信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(List<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        workflowService.deleteInstance(ids);
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 总体流程监听(例如: 草稿，撤销，退回，作废，终止，已完成，单任务完成等)
     * 正常使用只需#processEvent.flowCode=='leave1'
     * 示例为了方便则使用startsWith匹配了全部示例key
     *
     * @param processEvent 参数
     */
    @EventListener(condition = "#processEvent.flowCode=='applyVehicle'")
    public void processHandler(ProcessEvent processEvent) {
        log.info("当前任务执行了{}", processEvent.toString());
        CarApply testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId()));
        testLeave.setStatus(processEvent.getStatus());
        // 用于例如审批附件 审批意见等 存储到业务表内 自行根据业务实现存储流程
        Map<String, Object> params = processEvent.getParams();
        if (MapUtil.isNotEmpty(params)) {
            // 历史任务扩展(通常为附件)
            String hisTaskExt = Convert.toStr(params.get("hisTaskExt"));
            // 办理人
            String handler = Convert.toStr(params.get("handler"));
            // 办理意见
            String message = Convert.toStr(params.get("message"));
        }
        if (processEvent.getSubmit()) {
            testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
        }
        baseMapper.updateById(testLeave);
    }

    /**
     * 执行任务创建监听
     * 示例：也可通过  @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
     * 在方法中判断流程节点key
     * if ("xxx".equals(processTaskEvent.getNodeCode())) {
     * //执行业务逻辑
     * }
     *
     * @param processTaskEvent 参数
     */
    @EventListener(condition = "#processTaskEvent.flowCode=='applyVehicle'")
    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
        log.info("当前任务创建了{}", processTaskEvent.toString());
    }

    /**
     * 监听删除流程事件
     * 正常使用只需#processDeleteEvent.flowCode=='leave1'
     * 示例为了方便则使用startsWith匹配了全部示例key
     *
     * @param processDeleteEvent 参数
     */
    @EventListener(condition = "#processDeleteEvent.flowCode=='applyVehicle'")
    public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) {
        log.info("监听删除流程事件，当前任务执行了{}", processDeleteEvent.toString());
        CarApply testLeave = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId()));
        if (ObjectUtil.isNull(testLeave)) {
            return;
        }
        baseMapper.deleteById(testLeave.getId());
    }

    @Override
    public List<ApplyVo> matchingDegree(Long id) {
        ApplyBo applyBo = BeanUtil.copyProperties(baseMapper.selectById(id), ApplyBo.class);
        List<ApplyBo> applyBos = BeanUtil.copyToList(baseMapper.selectList(), ApplyBo.class);
        return getMatchingDegree(applyBo, applyBos);
    }

    /**
     * 获取匹配度
     * 根据用车开始时间、结束时间、经度、纬度等维度计算合乘匹配度
     *
     * @param bo  被匹配对象（发起人申请）
     * @param bos 待匹配对象列表
     * @return 匹配结果列表
     */
    @Override
    public List<ApplyVo> getMatchingDegree(ApplyBo bo, List<ApplyBo> bos) {
        List<ApplyVo> resultList = new ArrayList<>();

        // 参数校验
        if (bo == null || bos == null || bos.isEmpty()) {
            return resultList;
        }

        // 遍历每个待匹配申请单，计算匹配度
        for (ApplyBo candidateBo : bos) {
            // 跳过自己
            if (candidateBo.getId().equals(bo.getId())) {
                continue;
            }

            ApplyVo applyVo = new ApplyVo();
            applyVo.setId(candidateBo.getId());

            // 1. 计算时间匹配度（权重：20%）
            BigDecimal timeMatchingDegree = calculateTimeMatchingDegree(bo, candidateBo);
            applyVo.setTimeMatchingDegree(timeMatchingDegree);

            // 2. 计算地理位置匹配度（权重：40%）
            BigDecimal locationMatchingDegree = calculateLocationMatchingDegree(bo, candidateBo);
            applyVo.setLocationMatchingDegree(locationMatchingDegree);

            // 3. 计算用车类型匹配度（权重：20%）
            BigDecimal carTypeMatchingDegree = calculateCarTypeMatchingDegree(bo, candidateBo);
            applyVo.setCarTypeMatchingDegree(carTypeMatchingDegree);

            // 4. 计算用车事由匹配度（权重：20%）
            BigDecimal useReasonMatchingDegree = calculateUseReasonMatchingDegree(bo, candidateBo);
            applyVo.setUseReasonMatchingDegree(useReasonMatchingDegree);

            // 5. 计算总匹配度（加权平均：地理位置40% + 用车类型20% + 时间20% + 用车事由20%）
            BigDecimal totalMatchingDegree = locationMatchingDegree.multiply(new BigDecimal("0.4"))
                    .add(carTypeMatchingDegree.multiply(new BigDecimal("0.2")))
                    .add(timeMatchingDegree.multiply(new BigDecimal("0.2")))
                    .add(useReasonMatchingDegree.multiply(new BigDecimal("0.2")))
                    .setScale(2, RoundingMode.HALF_UP);
            applyVo.setTotalMatchingDegree(totalMatchingDegree);

            // 6. 生成匹配说明
            String description = generateMatchingDescription(timeMatchingDegree, locationMatchingDegree, carTypeMatchingDegree, useReasonMatchingDegree, totalMatchingDegree);
            applyVo.setMatchingDescription(description);

            resultList.add(applyVo);
        }

        // 按总匹配度降序排序
        resultList.sort((a, b) -> b.getTotalMatchingDegree().compareTo(a.getTotalMatchingDegree()));

        return resultList;
    }

    /**
     * 计算时间匹配度
     * 基于用车开始时间和结束时间计算匹配度，开始时间权重更高
     * 开始时间权重：70%，结束时间权重：30%
     *
     * @param source    被匹配对象
     * @param candidate 待匹配对象
     * @return 时间匹配度（0-100）
     */
    private BigDecimal calculateTimeMatchingDegree(ApplyBo source, ApplyBo candidate) {
        // 参数校验
        if (source.getStartTime() == null || source.getEndTime() == null ||
            candidate.getStartTime() == null || candidate.getEndTime() == null) {
            return BigDecimal.ZERO;
        }

        // 1. 计算开始时间匹配度（权重：70%）
        BigDecimal startTimeMatchingDegree = calculateSingleTimeMatchingDegree(
                source.getStartTime(), candidate.getStartTime());

        // 2. 计算结束时间匹配度（权重：30%）
        BigDecimal endTimeMatchingDegree = calculateSingleTimeMatchingDegree(
                source.getEndTime(), candidate.getEndTime());

        // 3. 加权计算总时间匹配度
        BigDecimal totalTimeMatchingDegree = startTimeMatchingDegree.multiply(new BigDecimal("0.7"))
                .add(endTimeMatchingDegree.multiply(new BigDecimal("0.3")))
                .setScale(2, RoundingMode.HALF_UP);

        return totalTimeMatchingDegree;
    }

    /**
     * 计算单个时间点的匹配度
     * 基于两个时间点之间的间隔计算匹配度
     *
     * @param sourceTime    被匹配时间
     * @param candidateTime 待匹配时间
     * @return 时间匹配度（0-100）
     */
    private BigDecimal calculateSingleTimeMatchingDegree(Date sourceTime, Date candidateTime) {
        // 计算时间间隔（毫秒）
        long gap = Math.abs(sourceTime.getTime() - candidateTime.getTime());

        // 将间隔转换为小时
        double gapHours = gap / (1000.0 * 60 * 60);

        // 根据时间间隔计算匹配度
        double matchingDegree;
        if (gapHours <= 0.5) {
            // 30分钟内：90-100分
            matchingDegree = 90 + (0.5 - gapHours) / 0.5 * 10;
        } else if (gapHours <= 1.0) {
            // 30分钟-1小时：80-90分
            matchingDegree = 80 + (1.0 - gapHours) / 0.5 * 10;
        } else if (gapHours <= 2.0) {
            // 1-2小时：60-80分
            matchingDegree = 60 + (2.0 - gapHours) / 1.0 * 20;
        } else if (gapHours <= 4.0) {
            // 2-4小时：40-60分
            matchingDegree = 40 + (4.0 - gapHours) / 2.0 * 20;
        } else if (gapHours <= 8.0) {
            // 4-8小时：20-40分
            matchingDegree = 20 + (8.0 - gapHours) / 4.0 * 20;
        } else if (gapHours <= 24.0) {
            // 8-24小时：0-20分
            matchingDegree = (24.0 - gapHours) / 16.0 * 20;
        } else {
            // 超过24小时：0分
            matchingDegree = 0;
        }

        return new BigDecimal(Math.max(0, matchingDegree)).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 计算地理位置匹配度
     * 基于经纬度坐标计算两个位置之间的距离，距离越近匹配度越高
     *
     * @param source    被匹配对象
     * @param candidate 待匹配对象
     * @return 地理位置匹配度（0-100）
     */
    private BigDecimal calculateLocationMatchingDegree(ApplyBo source, ApplyBo candidate) {
        // 参数校验
        if (StringUtils.isBlank(source.getLongitude()) || StringUtils.isBlank(source.getLatitude()) ||
            StringUtils.isBlank(candidate.getLongitude()) || StringUtils.isBlank(candidate.getLatitude())) {
            return BigDecimal.ZERO;
        }

        try {
            double sourceLng = Double.parseDouble(source.getLongitude());
            double sourceLat = Double.parseDouble(source.getLatitude());
            double candidateLng = Double.parseDouble(candidate.getLongitude());
            double candidateLat = Double.parseDouble(candidate.getLatitude());

            // 计算两点之间的距离（单位：公里）
            double distance = calculateDistance(sourceLat, sourceLng, candidateLat, candidateLng);

            // 根据距离计算匹配度
            // 距离在5公里内：90-100分
            // 距离在5-10公里：70-90分
            // 距离在10-20公里：50-70分
            // 距离在20-30公里：20-50分
            // 距离超过30公里：0-20分
            double matchingDegree;
            if (distance <= 5.0) {
                matchingDegree = 90 + (5.0 - distance) / 5.0 * 10; // 90-100分
            } else if (distance <= 10.0) {
                matchingDegree = 70 + (10.0 - distance) / 5.0 * 20; // 70-90分
            } else if (distance <= 20.0) {
                matchingDegree = 50 + (20.0 - distance) / 10.0 * 20; // 50-70分
            } else if (distance <= 30.0) {
                matchingDegree = 20 + (30.0 - distance) / 10.0 * 30; // 20-50分
            } else if (distance <= 50.0) {
                matchingDegree = (50.0 - distance) / 20.0 * 20; // 0-20分
            } else {
                matchingDegree = 0; // 超过50公里匹配度为0
            }

            return new BigDecimal(Math.max(0, matchingDegree)).setScale(2, RoundingMode.HALF_UP);

        } catch (NumberFormatException e) {
            log.warn("经纬度格式错误: source({}, {}), candidate({}, {})",
                    source.getLongitude(), source.getLatitude(),
                    candidate.getLongitude(), candidate.getLatitude());
            return BigDecimal.ZERO;
        }
    }

    /**
     * 计算用车类型匹配度
     * 基于用车类型的一致性计算匹配度
     *
     * @param source    被匹配对象
     * @param candidate 待匹配对象
     * @return 用车类型匹配度（0-100）
     */
    private BigDecimal calculateCarTypeMatchingDegree(ApplyBo source, ApplyBo candidate) {
        // 参数校验
        if (source.getCarType() == null || candidate.getCarType() == null) {
            return BigDecimal.ZERO;
        }

        // 用车类型完全匹配
        if (source.getCarType().equals(candidate.getCarType())) {
            return new BigDecimal("100.00");
        }

        // 用车类型不匹配，但可以根据业务规则设置部分匹配度
        // 这里可以根据实际业务需求定义不同用车类型之间的兼容性
        return calculateCarTypeCompatibility(source.getCarType(), candidate.getCarType());
    }

    /**
     * 计算用车类型兼容性
     * 根据实际用车类型定义不同类型之间的兼容程度
     *
     * @param sourceCarType    被匹配用车类型
     * @param candidateCarType 待匹配用车类型
     * @return 兼容性匹配度（0-100）
     */
    private BigDecimal calculateCarTypeCompatibility(Integer sourceCarType, Integer candidateCarType) {
        // 实际用车类型定义：
        // 1: 轿车
        // 2: 越野车(含SUV)
        // 3: 多功能乘用车/客车
        // 4: 执法执勤车
        // 5: 特种专业技术车
        // 6: 应急保障车
        // 7: 其他特种车

        // 兼容性规则：
        if ((sourceCarType == 1 && candidateCarType == 2) ||
            (sourceCarType == 2 && candidateCarType == 1)) {
            // 轿车与越野车有较高兼容性（都是常规乘用车）
            return new BigDecimal("80.00");
        } else if ((sourceCarType == 1 && candidateCarType == 3) ||
                   (sourceCarType == 3 && candidateCarType == 1) ||
                   (sourceCarType == 2 && candidateCarType == 3) ||
                   (sourceCarType == 3 && candidateCarType == 2)) {
            // 常规乘用车与多功能乘用车/客车有一定兼容性
            return new BigDecimal("70.00");
        } else if (sourceCarType == 4 || candidateCarType == 4) {
            // 执法执勤车与其他类型兼容性较低（专用性强）
            return new BigDecimal("30.00");
        } else if (sourceCarType == 5 || candidateCarType == 5) {
            // 特种专业技术车与其他类型兼容性很低（专业性强）
            return new BigDecimal("20.00");
        } else if (sourceCarType == 6 || candidateCarType == 6) {
            // 应急保障车与其他类型有基础兼容性
            return new BigDecimal("40.00");
        } else if (sourceCarType == 7 || candidateCarType == 7) {
            // 其他特种车与其他类型有基础兼容性
            return new BigDecimal("50.00");
        } else {
            // 其他情况默认较低兼容性
            return new BigDecimal("25.00");
        }
    }

    /**
     * 计算用车事由匹配度
     * 基于用车事由的一致性计算匹配度
     *
     * @param source    被匹配对象
     * @param candidate 待匹配对象
     * @return 用车事由匹配度（0-100）
     */
    private BigDecimal calculateUseReasonMatchingDegree(ApplyBo source, ApplyBo candidate) {
        // 参数校验
        if (source.getUseReason() == null || candidate.getUseReason() == null) {
            return BigDecimal.ZERO;
        }

        // 用车事由完全匹配
        if (source.getUseReason().equals(candidate.getUseReason())) {
            return new BigDecimal("100.00");
        }

        // 用车事由不匹配，但可以根据业务规则设置部分匹配度
        return calculateUseReasonCompatibility(source.getUseReason(), candidate.getUseReason());
    }

    /**
     * 计算用车事由兼容性
     * 根据实际用车事由定义不同事由之间的兼容程度
     *
     * @param sourceUseReason    被匹配用车事由
     * @param candidateUseReason 待匹配用车事由
     * @return 兼容性匹配度（0-100）
     */
    private BigDecimal calculateUseReasonCompatibility(Integer sourceUseReason, Integer candidateUseReason) {
        // 实际用车事由定义：
        // 1: 会议
        // 2: 调研
        // 3: 执法

        // 兼容性规则：
        if ((sourceUseReason == 1 && candidateUseReason == 2) ||
            (sourceUseReason == 2 && candidateUseReason == 1)) {
            // 会议与调研有较高兼容性（都是常规公务活动）
            return new BigDecimal("70.00");
        } else if (sourceUseReason == 3 || candidateUseReason == 3) {
            // 执法与其他事由兼容性较低（专业性强，时间要求严格）
            return new BigDecimal("30.00");
        } else {
            // 其他情况默认中等兼容性
            return new BigDecimal("50.00");
        }
    }

    /**
     * 计算两个经纬度坐标之间的距离（单位：公里）
     * 使用Haversine公式计算球面距离
     *
     * @param lat1 第一个点的纬度
     * @param lng1 第一个点的经度
     * @param lat2 第二个点的纬度
     * @param lng2 第二个点的经度
     * @return 距离（公里）
     */
    private double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
        // 地球半径（公里）
        final double EARTH_RADIUS = 6371.0;

        // 将角度转换为弧度
        double lat1Rad = Math.toRadians(lat1);
        double lng1Rad = Math.toRadians(lng1);
        double lat2Rad = Math.toRadians(lat2);
        double lng2Rad = Math.toRadians(lng2);

        // 计算差值
        double deltaLat = lat2Rad - lat1Rad;
        double deltaLng = lng2Rad - lng1Rad;

        // Haversine公式
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
                   Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                   Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return EARTH_RADIUS * c;
    }

    /**
     * 生成匹配说明
     * 根据各项匹配度生成详细的匹配说明
     * 地理位置权重40%，用车类型权重20%，时间权重20%，用车事由权重20%
     *
     * @param timeMatchingDegree      时间匹配度
     * @param locationMatchingDegree  地理位置匹配度
     * @param carTypeMatchingDegree   用车类型匹配度
     * @param useReasonMatchingDegree 用车事由匹配度
     * @param totalMatchingDegree     总匹配度
     * @return 匹配说明
     */
    private String generateMatchingDescription(BigDecimal timeMatchingDegree,
                                             BigDecimal locationMatchingDegree,
                                             BigDecimal carTypeMatchingDegree,
                                             BigDecimal useReasonMatchingDegree,
                                             BigDecimal totalMatchingDegree) {
        StringBuilder description = new StringBuilder();

        // 总体匹配度评价
        if (totalMatchingDegree.compareTo(new BigDecimal("85")) >= 0) {
            description.append("高度匹配：");
        } else if (totalMatchingDegree.compareTo(new BigDecimal("70")) >= 0) {
            description.append("较好匹配：");
        } else if (totalMatchingDegree.compareTo(new BigDecimal("50")) >= 0) {
            description.append("一般匹配：");
        } else {
            description.append("匹配度较低：");
        }

        // 地理位置匹配度说明（主要因素）
        if (locationMatchingDegree.compareTo(new BigDecimal("90")) >= 0) {
            description.append("地理位置极其接近");
        } else if (locationMatchingDegree.compareTo(new BigDecimal("70")) >= 0) {
            description.append("地理位置非常接近");
        } else if (locationMatchingDegree.compareTo(new BigDecimal("50")) >= 0) {
            description.append("地理位置较为接近");
        } else if (locationMatchingDegree.compareTo(new BigDecimal("30")) >= 0) {
            description.append("地理位置中等距离");
        } else if (locationMatchingDegree.compareTo(BigDecimal.ZERO) > 0) {
            description.append("地理位置距离较远");
        } else {
            description.append("地理位置信息缺失");
        }

        description.append("，");

        // 用车类型匹配度说明
        if (carTypeMatchingDegree.compareTo(new BigDecimal("100")) == 0) {
            description.append("用车类型完全匹配");
        } else if (carTypeMatchingDegree.compareTo(new BigDecimal("70")) >= 0) {
            description.append("用车类型高度兼容");
        } else if (carTypeMatchingDegree.compareTo(new BigDecimal("50")) >= 0) {
            description.append("用车类型基本兼容");
        } else if (carTypeMatchingDegree.compareTo(new BigDecimal("30")) >= 0) {
            description.append("用车类型兼容性较低");
        } else if (carTypeMatchingDegree.compareTo(BigDecimal.ZERO) > 0) {
            description.append("用车类型兼容性很低");
        } else {
            description.append("用车类型信息缺失");
        }

        description.append("，");

        // 用车事由匹配度说明
        if (useReasonMatchingDegree.compareTo(new BigDecimal("100")) == 0) {
            description.append("用车事由完全匹配");
        } else if (useReasonMatchingDegree.compareTo(new BigDecimal("70")) >= 0) {
            description.append("用车事由高度兼容");
        } else if (useReasonMatchingDegree.compareTo(new BigDecimal("50")) >= 0) {
            description.append("用车事由基本兼容");
        } else if (useReasonMatchingDegree.compareTo(new BigDecimal("30")) >= 0) {
            description.append("用车事由兼容性较低");
        } else if (useReasonMatchingDegree.compareTo(BigDecimal.ZERO) > 0) {
            description.append("用车事由兼容性很低");
        } else {
            description.append("用车事由信息缺失");
        }

        description.append("，");

        // 时间匹配度说明
        if (timeMatchingDegree.compareTo(new BigDecimal("85")) >= 0) {
            description.append("用车时间高度吻合");
        } else if (timeMatchingDegree.compareTo(new BigDecimal("65")) >= 0) {
            description.append("用车时间较为吻合");
        } else if (timeMatchingDegree.compareTo(new BigDecimal("40")) >= 0) {
            description.append("用车时间基本吻合");
        } else if (timeMatchingDegree.compareTo(new BigDecimal("20")) >= 0) {
            description.append("用车时间存在差异");
        } else {
            description.append("用车时间差异较大");
        }

        // 添加具体数值和权重说明
        description.append("（位置匹配度：").append(locationMatchingDegree).append("%[权重40%]，")
                  .append("类型匹配度：").append(carTypeMatchingDegree).append("%[权重20%]，")
                  .append("事由匹配度：").append(useReasonMatchingDegree).append("%[权重20%]，")
                  .append("时间匹配度：").append(timeMatchingDegree).append("%[权重20%]）");

        return description.toString();
    }
}
